local assets =
{
    -- Asset("ANIM", "anim/panda_fisherman_supply_pack.zip"),
    Asset( "IMAGE", "images/inventoryimages/npc_item_dining_table.tex" ),  -- 背包贴图
    Asset( "ATLAS", "images/inventoryimages/npc_item_dining_table.xml" ),
}
local function GetStringsTable()
    return TUNING.NPC_CHAT_TABLE[ type(TUNING.__NPC_LANGUAGE)=="function" and TUNING.__NPC_LANGUAGE() or TUNING.__NPC_LANGUAGE ] ["npc_item_dining_table"] or {}
end

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function GetItem_Base_prefab_name(item)
    return item.nameoverride or item.prefab
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function container_Widget_change(theContainer)

    local function Get_item_ask_table(inst)
        local _item_ask_table = nil
        if inst.components.container then
            _item_ask_table = inst.components.container._item_ask_table
        elseif inst.replica.container then
            _item_ask_table = inst.replica.container._item_ask_table            
        end
        return _item_ask_table
    end

    local function widget_update_fn_after(self,container,doer,...)
        ------------------------------------------------------------------------------
        --- 这里修改背景要求，比如数量要求。
        --- widget 的 children 修改
        ------------------------------------------------------------------------------
        local inst = container
        if self._item_ask_table == nil then
            self._item_ask_table = Get_item_ask_table(inst)
        end
        ------------------------------------------------------------------------------
        ------------------------------------------------------------------------------
        local child_fn = {
            ["ItemSlot"] = function(ItemSlot,num,_item_ask_table)
                --------------------------------------------
                if _item_ask_table ~= nil and _item_ask_table[num] ~= nil and _item_ask_table[num].name then
                    ItemSlot:ConvertToConstructionSlot(Ingredient(_item_ask_table[num].name, _item_ask_table[num].num or 1) , 0)
                end
                ItemSlot.base_scale = 1.5
                ItemSlot.highlight_scale = 2.5
                ItemSlot:SetScale(ItemSlot.base_scale)
                --------------------------------------------
            end,
            [GetStringsTable().button_text] = function(button)
                button:SetScale(1.5)
            end,
        }

        if self.children then
            -- 
            for v, child in pairs(self.children) do
                if v and child and child_fn[tostring(child)] then
                    if tostring(child) ~= "ItemSlot" then
                        child_fn[tostring(child)](child)
                    end
                end
            end
            ------ 格子的 table 位置会循环变化，用 self.inv 就能固定了
            for i, ItemSlot in ipairs(self.inv) do
                child_fn["ItemSlot"](ItemSlot,i,self._item_ask_table)                
            end

        end
        ------------------------------------------------------------------------------
        self:SetScale(1.2)
        self:MoveToFront()
        ------------------------------------------------------------------------------        
    end

    local params = {}
    params._theContainerWidget =
    {
        widget =
        {
            slotpos = {},
            animbank = "ui_construction_4x1",
            animbuild = "ui_construction_4x1",
            pos = Vector3(-400, 200, 0),
            top_align_tip = 50,
            buttoninfo =
            {
                text = GetStringsTable().button_text,
                position = Vector3(0, -94, 0),
            },
            -- ___npc_fn_before = widget_update_fn_before,
            ___npc_fn_after = widget_update_fn_after,
        },
        acceptsstacks = false,
        usespecificslotsforitems = true,
        type = "cooker",
    }

    for x = -1.5, 1.5, 1 do
        table.insert(params._theContainerWidget.widget.slotpos, Vector3(x * 110, 8, 0))
    end

    function params._theContainerWidget.itemtestfn(container, item, slot)
        local inst = container.inst
        local _item_ask_table = Get_item_ask_table(inst)

        if slot == nil and _item_ask_table then     --- 用快捷键或者手柄，会导致 slot 为 nil，先判断是否是目标物品，再用其他API自动放去目标位置
            for k, v in pairs(_item_ask_table) do
                if v and v.name == GetItem_Base_prefab_name(item) then
                    return true
                end
            end
        end

        if _item_ask_table and _item_ask_table[slot] and _item_ask_table[slot].name == GetItem_Base_prefab_name(item) then
            return true
        end

        return false
    end
    
    function params._theContainerWidget.widget.buttoninfo.fn(inst, doer)
        if inst.components.npc_base_lib then
            inst:PushEvent("button_click")
        elseif inst.replica.npc_base_lib then
            inst.replica.npc_base_lib:PushEvent("button_click")
        end
    end
    
    function params._theContainerWidget.widget.buttoninfo.validfn(inst)
        return inst:HasTag("item_ready")
    end


    theContainer:WidgetSetup("wobysmall",params._theContainerWidget)
    -- if TheWorld.ismastersim then
    --     theContainer:SetNumSlots(#params._theContainerWidget.widget.slotpos)
    -- end
end
local function add_container_before_not_ismastersim_retrun(inst)
	-------------------------------------------------------------------------------------------------
    ------ 添加背包container组件    --- 必须在 SetPristine 之后，
    -- local container_WidgetSetup = "wobysmall"
    if TheWorld.ismastersim then
        inst:AddComponent("container")
        inst.components.container.openlimit = 1  ---- 限制1个人打开
        -- inst.components.container:WidgetSetup(container_WidgetSetup)
        inst:DoTaskInTime(0.1,function()
            container_Widget_change(inst.components.container)            
        end)

    else
        inst:DoTaskInTime(0.1, function()
            if inst.replica then
                if inst.replica.container then
                --    inst.replica.container:WidgetSetup(container_WidgetSetup)
                    container_Widget_change(inst.replica.container)
                end
            end

        end)
    end
    -------------------------------------------------------------------------------------------------
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

local function itemtestfn(self,item,i)
    ------- 添加去server 上的 container 里，widget 那边得加上参数 usespecificslotsforitems = true
    local _item_ask_table = self._item_ask_table
    if _item_ask_table == nil then
        return false
    end
    if _item_ask_table[i] and _item_ask_table[i].name == GetItem_Base_prefab_name(item) then
        return true
    end
    return false
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function AskItem(inst)
    -- return {
    --     {name = "log" , num = 1},
    --     {name = "cutgrass" , num = 3},
    --     {name = "goldnugget" , num = 7},
    --     {name = "twigs" , num = 4},
    -- }
    return require("prefabs/items/24_dining_table_event")():GetFoods(inst)
end
local function ItemReadyCheck(inst)
    return require("prefabs/items/24_dining_table_event")():ItemReadyCheck(inst)    
end
local function Buyer_Appear(inst,doer)
    return require("prefabs/items/24_dining_table_event")():Buyer_Appear(inst,doer)    
end

local function AskItemInit(inst)
    inst:DoTaskInTime(0,function()
        local _item_ask_table = inst.npc_everything_data:Get("_item_ask_table") or AskItem(inst)
        inst.__net_str:set(json.encode(_item_ask_table))
        inst.components.container._item_ask_table = _item_ask_table
        inst.npc_everything_data:Set("_item_ask_table",_item_ask_table)
        --------------------------------------------------------------------
        ---- 指定物品到指定格子 ，widget 的itemtestfn 也需要配合
        inst.components.container.usespecificslotsforitems = true
        inst.components.container.itemtestfn = itemtestfn
        --------------------------------------------------------------------
    end)
    inst:DoTaskInTime(0.2,function()
        inst:PushEvent("canbeopened")
    end)
end

local function refresh_widget(inst)
    ---- 在server 上执行也能刷新给client
    if ItemReadyCheck(inst) then
        inst.npc_base_lib:RPC_AddTags({"item_ready"})
    else
        inst.npc_base_lib:RPC_RemoveTags({"item_ready"})
    end
    inst:DoTaskInTime(0.1,function()
        inst:PushEvent("refresh")        
    end)
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---- 处理拾取问题
local function go_in_inventory_event(inst)
    inst.components.container.canbeopened = false
    if inst.components.container:IsOpen() then
        inst.components.container:Close()
    end

    if not inst.components.container:IsEmpty() then
            local owner = inst.npc_base_lib:Get_Owner()
            if owner and owner:HasTag("player") then
                    local allitems = inst.components.container:GetAllItems()
                    inst.components.container:DropEverything()
                    for k, v in pairs(allitems) do
                        owner.components.inventory:GiveItem(v)                
                    end
            end
    end
    inst.AnimState:PlayAnimation("item")
end
local function drop_event(inst)
    inst.components.container.canbeopened = true
end

local function inventoryitem_event_init(inst)
    inst:ListenForEvent("onputininventory",go_in_inventory_event)
    inst:ListenForEvent("onownerputininventory",go_in_inventory_event)
    inst:ListenForEvent("onpickup",go_in_inventory_event)
    inst:ListenForEvent("ondropped",drop_event)
    inst:ListenForEvent("on_landed",function()
        -- print("on_landed")
        inst.AnimState:PlayAnimation("item")
        inst:DoTaskInTime(0.2,function()
            inst.AnimState:PlayAnimation("place")
            inst.AnimState:PushAnimation("idle")
        end)
    end)
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function fn()
    TheSim:LoadPrefabs({"quagmire_grill"})
    local inst = CreateEntity()

    inst.entity:AddTransform()
	inst.entity:AddNetwork()
	inst.entity:AddMiniMapEntity()

    inst.entity:AddAnimState()
    inst.AnimState:SetBank("quagmire_grill")
    inst.AnimState:SetBuild("quagmire_grill")
    inst.AnimState:PlayAnimation("item")
    inst.AnimState:SetScale(0.6,0.6,0.6)
    inst.AnimState:SetFinalOffset(-1)

	inst.MiniMapEntity:SetIcon("krampus_sack.png")

    inst:AddTag("structure")
    inst:AddTag("dining_table")
    inst:AddTag("npc_item_dining_table")

    
	MakeInventoryPhysics(inst)
    MakeInventoryFloatable(inst, "med", nil, 0.75)

    inst.entity:SetPristine()

    -----------------------------------------------------------------------------------------------
    inst.__net_str = net_string(inst.GUID, "npc_events_netvars","npc_item_dining_table") ----- 用json 传送数据同步
    -----------------------------------------------------------------------------------------------
    add_container_before_not_ismastersim_retrun(inst)
    -----------------------------------------------------------------------------------------------

    if not TheWorld.ismastersim then
        inst:ListenForEvent("npc_item_dining_table",function()
            if inst.replica.container then
                inst.replica.container._item_ask_table = json.decode(inst.__net_str:value())
                inst.replica.npc_base_lib:PushEvent("canbeopened")
            end
        end)
        return inst
    end

    inst:AddComponent("npc_base_lib")
    inst:AddComponent("npc_everything_data")


    inst:AddComponent("inspectable") --可检查组件

    inst:AddComponent("inventoryitem")
	inst.components.inventoryitem.cangoincontainer = true
    inventoryitem_event_init(inst)

    inst:AddComponent("named")
    inst.components.named:SetName(GetStringsTable().name)
    STRINGS.CHARACTERS.GENERIC.DESCRIBE[string.upper("npc_item_dining_table")] = GetStringsTable().inspect_str  --人物检查的描述

    ------------------------------------------------------------------------------------------------------------------------------
    inst.components.container.canbeopened = false
    ----------------------------------------------------------
        
    ----------------------------------------------------------

    inst:ListenForEvent("onopen",function(_,_table)
        if _table and _table.doer then
            if _table.doer.sg and not _table.doer.sg:HasStateTag("busy") then
                _table.doer.sg:GoToState("constructing")
                -- _table.doer.components.playercontroller:Enable(false)
            end
        end
        inst.AnimState:PlayAnimation("cooking_grill_big",true)
    end)

    inst:ListenForEvent("onclose",function(_,_table)
        if _table and _table.doer then
            if _table.doer.sg and not _table.doer.sg:HasStateTag("busy") then
                -- _table.doer.sg:GoToState("idle")
                _table.doer.sg:GoToState("construct")
                -- _table.doer.components.playercontroller:Enable(true)
            end
            inst:DoTaskInTime(0.1,function()
                    if inst.npc_base_lib:Get_Owner(true) == nil then
                            if ItemReadyCheck(inst) then
                                Buyer_Appear(inst,_table.doer)
                            end               
                    end
            end)
        end
        if inst.components.container and not inst.components.container:IsEmpty() then
            inst.AnimState:PlayAnimation("cooking_grill_big",true)
        else
            inst.AnimState:PlayAnimation("idle",true)
        end

    end)
    inst:ListenForEvent("button_click",function()
        inst.components.container:Close()
    end)
    inst:ListenForEvent("canbeopened",function()
        if inst.npc_base_lib:Get_Owner(true) ~= nil then
            inst.components.container.canbeopened = false
        else
            inst.components.container.canbeopened = true
        end    
    end)

    inst:ListenForEvent("itemget",refresh_widget)
    inst:ListenForEvent("itemlose",refresh_widget)
    ------------------------------------------------------------------------------------------------------------------------------
    AskItemInit(inst)
    ------------------------------------------------------------------------------------------------------------------------------

    return inst
end

return Prefab("npc_item_dining_table", fn,assets)